package dbb

import (
	"reflect"
	"strings"

	"fyne.io/fyne/v2"
	"fyne.io/fyne/v2/container"
	"fyne.io/fyne/v2/widget"
	"github.com/gogf/gf/v2/container/garray"
	"github.com/gogf/gf/v2/container/gmap"
	"github.com/gogf/gf/v2/database/gdb"
	"github.com/gogf/gf/v2/os/gfile"
	"github.com/gogf/gf/v2/util/gconv"
	"github.com/goki/ki/ki"
	"github.com/goki/ki/kit"
	octicons "github.com/lusingander/fyne-octicons"
	"github.com/y2h/fyne_poem/util"
	"github.com/y2h/fyne_poem/widgets"
	"xorm.io/xorm/schemas"
)

// 显示数据库名、表名、列名
var Treee *widget.Tree

type YhNodeDB struct {
	ki.Node
}

var YhNodeDBProps = ki.Props{
	// "intprop":    -17,
	// "floatprop":  3.1415,
	// "stringprop": "type string",
}
var KiT_YhNodeDB = kit.Types.AddType(&YhNodeDB{}, YhNodeDBProps)

var parent = YhNodeDB{}

// 字段结点
var zdnd ki.Ki
var typ reflect.Type

func init() {
	parent.InitName(&parent, "root")
	typ = reflect.TypeOf(parent)
}
func msg(s string) {
	Me.Msg.SetText(s)
}

// 构建数据库、表、字段树形结构
func SetKi(db gdb.DB, dbname string) {
	engine := gf2xorm(db)
	if engine == nil {
		msg("nil engine")
		return
	}
	// tblss, _ := db.Tables(Ctx)
	// Me.Tbls.SetArray(tblss)
	tbls, _ := engine.DBMetas()
	for i := 0; i < len(tbls); i++ {
		Me.Tblsm[tbls[i].Name] = tbls[i]
	}
	// parent.DeleteChildren(true)
	dbnode := parent.AddNewChild(typ, dbname)
	dbnode.SetProp("numtbl", len(tbls))
	ktbls := "Tables(" + gconv.String(len(tbls)) + ")"
	tblnode := dbnode.AddNewChild(typ, ktbls)
	for _, tbl := range tbls {
		tblnd := tblnode.AddNewChild(typ, tbl.Name)
		cols := garray.NewStrArrayFrom(tbl.ColumnsSeq(), true).FilterEmpty()
		zdnd = tblnd.AddNewChild(typ, "")
		zdnd.SetName("字段(" + gconv.String(cols.Len()) + ")")
		cols.Iterator(func(k int, v string) bool {
			zdnd.AddNewChild(typ, v)
			return true
		})

		idxs := gmap.NewStrAnyMap(true)
		for k, v := range tbl.Indexes {
			idxs.Set(k, v)
		}
		idxnd := tblnd.AddNewChild(typ, "Indexes")
		idxnd.SetName("Indexes(" + gconv.String(idxs.Size()) + ")")
		idxs.Iterator(func(k string, v interface{}) bool {
			idxnd.AddNewChild(typ, v.(*schemas.Index).Name)
			return true
		})
		tblnd.AddNewChild(typ, "触发器")
	}
}

var openTbls = []string{}

func RefreshDbtree() {
	Me.Dbtree.ChildUIDs = func(tni widget.TreeNodeID) []widget.TreeNodeID {
		if tni == "" {
			res := make([]string, 0, 20)
			clds := *parent.Children()
			for _, cld := range clds {
				res = append(res, cld.Path())
			}
			return res
		}

		node := parent.FindPath(tni)
		res := make([]string, 0, 20)
		for _, cld := range *node.Children() {
			res = append(res, cld.Path())
		}
		// fmt.Printf("res1: %v\n", res)
		return res
	}
	Me.Dbtree.IsBranch = func(tni widget.TreeNodeID) bool {
		if tni == "" {
			return parent.HasChildren()
		}

		return parent.FindPath(tni).HasChildren()
	}
	Me.Dbtree.CreateNode = func(b bool) fyne.CanvasObject {
		return widgets.NewClickLbl("Template Object", nil, nil, nil)
	}
	Me.Dbtree.UpdateNode = func(tni widget.TreeNodeID, b bool,
		co fyne.CanvasObject) {
		lbl := co.(*widgets.Clicklbl)
		v, found := garray.NewStrArrayFrom(strings.Split(
			parent.FindPath(tni).Path(), "/")).PopRight()
		if found {
			lbl.SetText(v)
		}
		lbl.OnRightTapped = func() {
			pos := Me.D.AbsolutePositionForObject(lbl)
			treepop1(v)
			widget.ShowPopUpAtPosition(treepop, Me.D.CanvasForObject(lbl), pos)
		}
		// lbl.SetText(tni)
		lbl.OnDoubleTapped = func() {
			Me.Dbtree.Select(tni)
			if !Me.Tbls.Contains(v) {
				// 双击表名时才执行下面的代码
				return
			}
			txt := v + "(" +
				gfile.Name(Me.Db.GetConfig().Name) + ")"

			if util.IsInSlice(txt, openTbls) {
				// 如果该表已打开，则选择相应标签
				for _, v := range Me.Tabs.Items {
					if txt == v.Text {
						Me.Tabs.Select(v)
					}
				}
				return
			}
			openTbls = append(openTbls, txt)
			dataBrowser := container.NewTabItemWithIcon(txt,
				octicons.NoteIcon(),
				Tbs(Me.Db, v, Me.Msg, Me.W, Me.A))

			Me.Tabs.Append(dataBrowser)
			Me.Tabs.Select(dataBrowser)
		}
		lbl.OnTapped = func() {
			Me.Dbtree.Select(tni)
		}
	}
	Me.Dbtree.Refresh()
}
